import esbuild from 'esbuild'
import MagicString from 'magic-string'
import path from 'path'
import rollup from 'rollup'
import { normalizePath } from 'vite'

export function esbuildMinify(options: import('esbuild').TransformOptions = {}): rollup.Plugin {
  const { minify, minifyWhitespace, minifyIdentifiers, minifySyntax } = options

  const minifyOptions: import('esbuild').TransformOptions = {
    sourcemap: true,
    minify,
    minifyWhitespace,
    minifyIdentifiers,
    minifySyntax
  }
  return {
    name: 'esbuild:minify',
    renderChunk(code) {
      return esbuild.transform(code, minifyOptions)
    }
  }
}

export function replaceDir(mainDir: string, rendererDir: string, sourcemap?: boolean): rollup.Plugin {
  return {
    name: 'electron:replaceDir',
    renderStart(options) {
      sourcemap = !!options.sourcemap
    },
    renderChunk(code, { fileName }) {
      const absDirName = path.join(mainDir, path.dirname(fileName))
      const relMainDir = normalizePath(path.relative(absDirName, mainDir))
      const relRendererDir = normalizePath(path.relative(absDirName, rendererDir))
      const mainDirResult = `(__dirname + ${JSON.stringify('/' + relMainDir)})`
      const rendererDirResult = `(__dirname + ${JSON.stringify('/' + relRendererDir)})`
      let s: MagicString
      let hasReplaced = false

      for (const match of code.matchAll(/(?<![\w$])(__MAIN_DIR__|__RENDERER_DIR__)(?![\w$])/g)) {
        s = s! ?? new MagicString(code)
        const start = match.index ?? 0
        const end = start + match[0].length
        hasReplaced = true
        s.overwrite(start, end, match[0] === '__MAIN_DIR__' ? mainDirResult : rendererDirResult)
      }

      if (!hasReplaced) {
        return null
      }

      return { code: s!.toString(), map: sourcemap ? s!.generateMap({ hires: true }) : undefined }
    }
  }
}
